<!-- Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
-->
<!-- 
* @desc:任务编排新增弹窗
* @fileName:Operation.vue
* @author:chenxiaofeng@yzbdl.ac.cn
* @date:2022-4-15
!-->
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import { ElMessage, FormInstance } from "element-plus";
import { Delete } from "@element-plus/icons-vue";
import { getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance() as any;

const props = defineProps({
  // 保存方法回调
  saveArrangement: Function as any,
  // 编辑方法回调
  editArrangement: Function as any,
  // 新增或修改标识
  addOrEdit: String,
  // 点击修改后的单条数据值
  oneUserInfo: Object,
  // 分组ID
  groupId: {
    type: String,
  },
});

const listData = reactive({
  serverNodeList: [] as any, //服务节点下拉选项列表值
  groupTree: [] as any, //资源树下拉选项值
  resouceList: [] as any, //资源列表选项值
  taskList: [] as any, //任务配置参数列表
  groupOptions: [], //分组下拉数据
  groupTreeValue: "", //任务资源
});

/**
 * 定义任务资源参数类型
 */
const paramTypeList = [
  { name: "字符串", value: "String" },
  { name: "数字", value: "Number" },
  { name: "JSON对象", value: "JsonObject" },
  { name: "数组", value: "Arr" },
  { name: "布尔", value: "Boolean" },
  { name: "Null", value: "Null" },
];

/**
 * 定义日志等级枚举
 */
const logLevel = [
  { name: "基本(Basic)", value: 3 },
  { name: "详细(Detailed)", value: 4 },
  { name: "调试(Debug)", value: 5 },
  { name: "行级(Row level)", value: 6 },
  { name: "最小(Minimal)", value: 2 },
  { name: "错误(ERROR)", value: 1 },
  { name: "无(Nothing)", value: 0 },
];
const ruleFormRef = ref<FormInstance>();
/**
 * 表单数据
 */
let ruleForm: any = reactive({
  taskName: "",
  taskCron: "",
  serverProgramId: "",
  taskResourceId: "",
  jsonConfig: "",
  groupId: props.groupId === "-1" ? "" : props.groupId,
  logLevel: "",
  remark: "",
  status: 2,
});

const labelPosition = ref("top");

/**
 * 定义校验规则
 */
const rules: any = reactive({
  taskName: [
    { required: true, message: "请输入任务名称", trigger: "blur" },
    { max: 64, message: "任务名称最多能输入64个字符", trigger: "blur" },
  ],
  taskCron: [
    { required: true, message: "cron表达式不能为空", trigger: "change" },
  ],
  serverProgramId: [
    { required: true, message: "请选择服务节点", trigger: "change" },
  ],
  taskResourceId: [
    { required: true, message: "请选择任务资源", trigger: "change" },
  ],
  groupId: [{ required: true, message: "请选择所在分组", trigger: "change" }],
  logLevel: [{ required: true, message: "请选择日志等级", trigger: "change" }],
  status: [{ required: true, message: "请选择启用状态", trigger: "change" }],
});

/**
 * 提交表单
 * @reture viod
 */
const submitForm = async (
  formEl: FormInstance | undefined,
  isHide: boolean = false
) => {
  listData.taskList.length === 0
    ? (ruleForm.jsonConfig = "")
    : (ruleForm.jsonConfig = JSON.stringify(listData.taskList));
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      props.addOrEdit === "add"
        ? props.saveArrangement(ruleForm, isHide)
        : props.editArrangement(ruleForm);
    } else {
      console.log("error submit!", fields);
    }
  });
};

/**
 * 获取服务节点
 * @reture viod
 */
const getServerNodeList = () => {
  const res = proxy.$HTTP.get({
    url: `/task/plan/serverProgramList`,
  });
  res
    .then((res: any) => {
      if (res.isOk) {
        listData.serverNodeList = res.data;
      }
    })
    .catch((response: any) => {
      ElMessage.error(response.data);
    });
};

/**
 * 获取资源树
 * @reture viod
 */
const getGroupTree = () => {
  const res = proxy.$HTTP.get({
    url: `/task/plan/taskResourceGroupTree`,
  });
  res
    .then((res: any) => {
      if (res.isOk) {
        listData.groupTree = res.data;
      }
    })
    .catch((response: any) => {
      ElMessage.error(response.data);
    });
};

/**
 * 任务资源下拉选择，根据资源分组ID获取资源列表
 * @param data 选择中树的节点信息
 * @reture viod
 */
const getGroupOne = (data: any) => {
  listData.resouceList = [];
  ruleForm.taskResourceId = "";
  const res = proxy.$HTTP.get({
    url: `/task/plan/taskResourceList/` + data.id,
  });
  res
    .then((res: any) => {
      if (res.isOk) {
        listData.resouceList = res.data;
      }
    })
    .catch((response: any) => {
      ElMessage.error(response.data);
    });
};

/**
 * 添加一行任务配置
 * @reture viod
 */
const addConfigOne = () => {
  let json = { paramName: "", paramType: "", paramValue: "" };
  listData.taskList.push(json);
};

/**
 * 删除任务配置
 * @param index 删除任务的下标
 * @reture viod
 */
const delConfigONe = (index: number) => {
  listData.taskList.splice(index, 1);
};

/**
 * 获取分组
 * /task/plan/group/tree/list
 * @reture viod
 */
const getGroupList = () => {
  const res = proxy.$HTTP.get({
    url: `/task/plan/group/tree`,
  });
  res
    .then((res: any) => {
      if (res.isOk) {
        listData.groupOptions = res.data;
      }
    })
    .catch((response: any) => {
      ElMessage.error(response.data);
    });
};

/**
 * 获取分组值
 * @param id 删除任务的下标
 * @reture viod
 */
const getGroupValue = (id: string) => {
  ruleForm.groupId = id;
};

/**
 * 根据状态返回中文
 * @param s 状态数字
 * @reture 状态中文
 */
const showStatus = (s: number) => {
  if (s === 1) {
    return "运行中";
  } else if (s === 2) {
    return "异常";
  } else {
    return "停止";
  }
};

/**
 * 重置表单
 */
const resetForm = () => {
  if (!ruleFormRef.value) return;
  ruleFormRef.value?.resetFields();
};

defineExpose({ resetForm });

/**
 * 初始化加载
 */
onMounted(() => {
  // 获取服务节点下拉选项值
  getServerNodeList();
  // 获取资源分组树下拉选项值
  getGroupTree();
  // 获取所在分组下拉选项值
  getGroupList();
  // 点击修改单条数据时，回显
  setTimeout(() => {
    let userInfo = { ...props.oneUserInfo };
    if (JSON.stringify(props.oneUserInfo) !== "{}") {
      getGroupOne({ id: userInfo.taskResourceGroupId });
      if (typeof userInfo.jsonConfig !== "undefined") {
        userInfo.jsonConfig === "" || userInfo.jsonConfig === null
          ? (ruleForm.taskName = [])
          : (ruleForm.taskName = JSON.parse(userInfo.jsonConfig));
      }
      ruleForm.taskName = userInfo.taskName;
      ruleForm.taskCron = userInfo.taskCron;
      ruleForm.serverProgramId = userInfo.serverProgramId;
      ruleForm.taskResourceId = userInfo.taskResourceId;
      ruleForm.jsonConfig = userInfo.jsonConfig;
      ruleForm.groupId = userInfo.groupId;
      ruleForm.logLevel = userInfo.logLevel;
      ruleForm.remark = userInfo.remark;
      ruleForm.status = Number(userInfo.status);
      ruleForm.id = userInfo.id;
      listData.groupTreeValue = userInfo.taskResourceGroupId;
      listData.taskList = JSON.parse(userInfo.jsonConfig);
    }
  }, 500);
});

const treeProps = {
  label: "groupName",
  value: "id",
  children: "children",
};

const groupProps = {
  label: "groupName",
  value: "id",
  children: "children",
};
const state = reactive({
  cronPopover: false,
  cron: "",
});
const changeCron = (val: string) => {
  if (typeof val !== "string") return false;
  ruleForm.taskCron = val;
};
const togglePopover = (bol: boolean) => {
  state.cronPopover = bol;
  console.log(bol);
};
</script>

<template>
  <div class="operation">
    <el-form
      ref="ruleFormRef"
      :model="ruleForm"
      :rules="rules"
      :label-position="labelPosition"
      label-width="120px"
      class="demo-ruleForm"
    >
      <el-form-item label="任务名称" prop="taskName">
        <el-input
          v-model="ruleForm.taskName"
          placeholder="请输入任务名称"
          show-word-limit
          maxlength="64"
        />
      </el-form-item>
      <el-form-item label="执行周期" prop="taskCron">
        <div class="cron">
          <el-popover
            :visible="state.cronPopover"
            width="700px"
            trigger="manual"
          >
            <vue3Cron
              @change="changeCron"
              @close="togglePopover(false)"
              :cronValue="ruleForm.taskCron"
              max-height="400px"
              i18n="cn"
            ></vue3Cron>
            <template #reference>
              <div>
                <el-input
                  v-model="ruleForm.taskCron"
                  clearable
                  @click="togglePopover(true)"
                  placeholder="请选择执行周期"
                ></el-input>
              </div>
            </template>
          </el-popover>
        </div>
      </el-form-item>
      <el-form-item label="服务节点" prop="serverProgramId">
        <el-select
          v-model="ruleForm.serverProgramId"
          class="m-2"
          placeholder="请选择服务节点"
        >
          <el-option
            v-for="item in listData.serverNodeList"
            :key="item.id"
            :label="item.programName"
            :value="item.id"
            :disabled="item.status !== 1"
          >
            <span class="options-label">{{ item.programName }}</span
            ><span class="options-status">{{ showStatus(item.status) }}</span>
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="任务资源" prop="taskResourceId">
        <template #default="scope">
          <div class="task-resource">
            <el-tree-select
              check-strictly
              :props="treeProps"
              node-key="id"
              clearable
              :data="listData.groupTree"
              :default-expand-all="true"
              v-model="listData.groupTreeValue"
              class="task-resource-select"
              placeholder="请选择分组资源"
              @node-click="getGroupOne"
            />
            <el-select
              v-model="ruleForm.taskResourceId"
              class="task-resource-select"
              placeholder="请选择资源"
            >
              <el-option
                v-for="item in listData.resouceList"
                :key="item.id"
                :label="item.resourceName"
                :value="item.id"
              />
            </el-select>
          </div>
        </template>
      </el-form-item>
      <el-form-item
        label="任务配置"
        prop="jsonConfig"
        :inline-message="false"
        :show-message="false"
      >
        <template #default="scope">
          <div class="config">
            <div
              class="task-config"
              v-for="(item, indx) in listData.taskList"
              :key="indx"
            >
              <el-input
                v-model="item.paramName"
                class="w-1"
                clearable
                maxlength="50"
                placeholder="请输入参数名称"
              ></el-input>
              <el-select
                v-model="item.paramType"
                class="w-1"
                clearable
                placeholder="请选择数据类型"
              >
                <el-option
                  v-for="item in paramTypeList"
                  :key="item.value"
                  :label="item.name"
                  :value="item.value"
                />
              </el-select>
              <el-input
                clearable
                class="w-2"
                maxlength="50"
                v-model="item.paramValue"
                placeholder="请输入参数值"
              ></el-input>
              <div @click="delConfigONe(indx)" class="op-icon">
                <el-icon><delete /></el-icon>
              </div>
            </div>
            <div class="op-icon add" @click="addConfigOne">+</div>
          </div>
        </template>
      </el-form-item>
      <el-form-item label="所在分组" prop="groupId">
        <el-tree-select
          check-strictly
          :props="groupProps"
          node-key="id"
          clearable
          :data="listData.groupOptions"
          :default-expand-all="true"
          v-model="ruleForm.groupId"
          class="task-resource-select"
          placeholder="请选择所在分组"
          @node-click="getGroupValue"
        />
      </el-form-item>
      <el-form-item label="日志等级" prop="logLevel">
        <el-select
          v-model="ruleForm.logLevel"
          class="m-2"
          clearable
          placeholder="请选择资源"
        >
          <el-option
            v-for="item in logLevel"
            :key="item.value"
            :label="item.name"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="任务状态" prop="status">
        <el-radio-group v-model="ruleForm.status">
          <el-radio :label="2">启用</el-radio>
          <el-radio :label="1">禁用</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="备注" prop="remark">
        <el-input
          v-model="ruleForm.remark"
          clearable
          maxlength="500"
          type="textarea"
          placeholder="请输入备注"
        />
      </el-form-item>
      <el-form-item class="click-button">
        <el-button
          @click="submitForm(ruleFormRef, true)"
          v-if="props.addOrEdit === 'add'"
          >保存并创建下一个任务</el-button
        >
        <el-button @click="submitForm(ruleFormRef)">确定</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<style>
.el-dialog__header {
  border-bottom: 1px solid #dedede;
  margin-right: 0;
}
</style>
<style scoped lang="scss">
.task-resource {
  display: flex;
  width: 100%;
  .task-resource-select {
    flex: 1;
    &:nth-of-type(1) {
      margin-right: 5px;
    }
    &:nth-of-type(2) {
      margin-left: 5px;
    }
  }
}
.cron {
  width: 100%;
}
.options-label {
  float: left;
}
.options-status {
  float: right;
  color: #999;
  font-size: 12px;
}
.w-1 {
  width: 200px !important;
  margin-right: 10px;
  margin-bottom: 10px;
}
.w-2 {
  width: 220px;
  margin-right: 10px;
}
.op-icon {
  border: 1px solid #ccc;
  width: 40px;
  height: 38px;
  text-align: center;
  line-height: 38px;
  cursor: pointer;
  &.add {
    font-size: 22px;
  }
}
.task-config {
  display: flex;
}
.el-select {
  width: 100%;
}
:deep(.el-form-item__label) {
  font-family: PingFang SC;
  font-weight: 700;
  color: #000000;
  font-size: 14px;
}
:deep(.el-input) {
  height: 40px;
  background-color: #ffffff;
}
:deep(.el-textarea) {
  height: 100px;
  background-color: #ffffff;
  .el-textarea__inner {
    height: 100px;
  }
}
.click-button {
  :deep(.el-form-item__content) {
    display: flex;
    justify-content: flex-end;
    .el-button {
      height: 40px;
      background-color: #ffffff;
      border: 1px solid;
      border-color: #cccccc;
    }
  }
}
</style>
